﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using SimpleRssReader.Model;
using Windows8Accelerator.Core.Xaml;
using Windows.Web.Syndication;
using Windows.Data.Html;
using System.Text.RegularExpressions;
using Windows8Accelerator.Core.Xaml.Helpers;

namespace SimpleRssReader.DataSources
{
    public class RssDataSource : IDataSource
    {
        public async Task<ObservableCollection<Blog>> RetrieveBlogsWithLatestPostsAsync(int maxPostsPerBlog)
        {
            var blogs = await RetrieveBlogsAsync();

            foreach (var blog in blogs)
            {
                try
                {
                    var posts = await RetrieveLatestPostsAsync(blog, maxPostsPerBlog);
                    ListHelper.MergeLists(blog.Posts, posts, (p) => p.Id, MergeMode.Add);
                }
                catch { }
            }

            return blogs;
        }

        private async Task<ObservableCollection<Blog>> RetrieveBlogsAsync()
        {
            var blogs = new ObservableCollection<Blog>();
            blogs.Add(new Blog()
            {
                Id = 1,
                Name = "Danilo Bordini",
                RssUrl = "http://blogs.technet.com/b/dbordini/rss.aspx",
                Posts = new List<Post>(),
            });
            blogs.Add(new Blog()
            {
                Id = 2,
                Name = "Fernando Martin",
                RssUrl = "http://fernandomartin.azurewebsites.net/?feed=rss2",
                Posts = new List<Post>(),
            });
            blogs.Add(new Blog()
            {
                Id = 3,
                Name = "Osvaldo Daibert",
                RssUrl = "http://blogs.msdn.com/b/daibert/rss.aspx",
                Posts = new List<Post>(),
            });
            blogs.Add(new Blog()
            {
                Id = 4,
                Name = "Rogerio Cordeiro",
                RssUrl = "http://blogs.msdn.com/b/rogerioc/rss.aspx",
                Posts = new List<Post>(),
            });
            blogs.Add(new Blog()
            {
                Id = 5,
                Name = "Vinicius Souza",
                RssUrl = "http://viniciussouza.azurewebsites.net/feed/",
                Posts = new List<Post>(),
            });
            blogs.Add(new Blog()
            {
                Id = 6,
                Name = "Vitor Ciaramella",
                RssUrl = "http://blogs.msdn.com/b/vitorcia/rss.aspx",
                Posts = new List<Post>(),
            });
            return blogs;
        }


        public async Task<ObservableCollection<Post>> RetrieveLatestPostsAsync(Blog blog, int maxPosts)
        {
            var client = new SyndicationClient
            {
                BypassCacheOnRetrieve = true
            };

            client.SetRequestHeader("user-agent",
                                    "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

            var feedUri = new Uri(blog.RssUrl);
            var feed = await client.RetrieveFeedAsync(feedUri);

            var topItems = feed.Items.OrderByDescending(x => x.PublishedDate).Take(maxPosts).ToList();

            var posts = new ObservableCollection<Post>();
            foreach (var item in topItems)
            {
                try
                {
                    var post = new Post()
                    {
                        Id = item.Id,
                        Title = item.Title.Text,
                        Summary = HtmlUtilities.ConvertToText(item.Summary != null ? item.Summary.Text : ""),
                        Body = item.Content != null ? item.Content.Text : item.Summary != null ? item.Summary.Text : "",
                        Image = GetImageFromFeedItem(item.NodeValue),
                        Date = item.PublishedDate.DateTime,
                        Blog = blog,
                        Url = GetUrlFromFeedItem(item),
                    };
                    posts.Add(post);
                }
                catch { }
            }
            return posts;
        }

        private string GetUrlFromFeedItem(SyndicationItem item)
        {
            if (item.ItemUri != null)
                return item.ItemUri.OriginalString;
            if (item.Links != null && item.Links.Count > 0)
                return item.Links[0].NodeValue;
            return item.Id;
        }

        private string GetImageFromFeedItem(string feedItem)
        {
            Match match = Regex.Match(feedItem, @"(?<=<img\s+[^>]*?src=(?<q>['""]))(?<url>.+?)(?=\k<q>)", RegexOptions.IgnoreCase);
            var imageExtension = new[] { "jpg", ".png", ".bmp" };

            string imageUrl = string.Empty;
            if (match.Success)
            {
                imageUrl = match.Groups[0].Value;
            }

            if(!imageExtension.Any((i)=>imageUrl.EndsWith(i)))
                return string.Empty;

            return imageUrl; 
        }


        public async Task<Post> RetrieveFullPostAsync(Post post)
        {
            return post;
        }
    }
}
